﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RAD.LightOne
{
    #region Documentation
    /// <summary>
    /// Classe auxiliar na tarefa de expor os atributos marcados em uma classe que herde de <see cref="MyObject"/>.
    /// Singleton.
    /// </summary>
    #endregion
    public sealed class MetadatHelper<T> where T: MyObject
    {
        #region Fields

        private static MetadatHelper<T> instance;
        private static object locker;

        #endregion

        #region Properties
        #region Documentation
        /// <summary>
        /// Tabela principal em uma hierarquia de herança
        /// </summary>
        #endregion
        public string MainTable
        {
            get;
            private set;
        }

        #region Documentation
        /// <summary>
        /// Todas as tabelas relacionadas ao tipo T.
        /// </summary>
        #endregion
        public string[] Tables
        {
            get;
            private set;
        }

        #region Documentation
        /// <summary>
        /// Dicionário de campos, retorna o campo definido no atributo <see cref="DBFieldAttribute"/> segundo o nome da propriedade na classe do tipo T.
        /// </summary>
        #endregion
        public Dictionary<string, string> Fields
        {
            get;
            private set;
        }
        #endregion

        #region Constructors
        
        static MetadatHelper()
        {
            locker = new object();
        }

        private MetadatHelper()
        {
            this.Fields = new Dictionary<string,string>();

            this.MainTable = MetadataReader.ExtractMainTable(typeof(T));
            this.Tables = MetadataReader.ExtractTables(typeof(T));
            var infos = MetadataReader.ExtractDBFieldMarked(typeof(T));

            var keys = FieldNameAttribute.GetDefinedAttributes(typeof(T));

            foreach (var k in keys)
            {
                switch(k.Key)
                {
                    case KeyField.ID:
                        Fields.Add("Id", k.FieldName);
                        break;
                    case KeyField.ClassName:
                        Fields.Add("ClassName", k.FieldName);
                        break;
                    case KeyField.LastPersistence:
                        Fields.Add("LastPersistence", k.FieldName);
                        break;
                }
            }

            foreach (var info in infos)
            {
                var attrib = DBFieldAttribute.GetDefinedAttribute(info);
                this.Fields.Add(info.Name, attrib.FieldName);
            }
        }

        #endregion

        #region Methods

        #region Documentation
        /// <summary>
        /// Retorna a instância do auxiliar de metadados.
        /// </summary>
        #endregion
        public static MetadatHelper<T> Instance()
        {
            lock (locker)
            {
                if (instance == null)
                {
                    instance = new MetadatHelper<T>();
                }
                return instance;
            }
        }

        #endregion
    }
}
